#include "logmessage.hpp"
#include <string>
#include <unordered_map>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;

const string WebRoot = "./webroot";
const string SEP = "\r\n";

struct Request
{
    string _method;
    string _url;
    string _url_args;
    string _http_version;
    string _path;
    string _suffix;
    unordered_map<string, string> _header;
    string _content;

    bool Deserialize(string &buffer) // 传入应用层缓冲区进行解析
    {
        int left = 0, right = 0; // 标定当前解析区间的左右端点
        // 1.解析请求行
        right = buffer.find(SEP);
        if (right == string::npos)
        {
            return false;
        }
        stringstream ss(buffer.substr(left, right - left));
        ss >> _method >> _url >> _http_version;
        // 解析url参数
        if(_method == "GET")
        {
            int pos = _url.find('?');
            if(pos != string::npos)
            {
                _url_args = _url.substr(pos+1);
                _url.erase(pos);
            }
        }
        // 解析文件路径
        _path = WebRoot;
        if (_url != "/")
            _path += _url;
        else
            _path += "/index.html";
        // 解析文件后缀
        int pos = _url.rfind('.');
        if(pos == string::npos)
            _suffix = "html";
        else    
            _suffix = _url.substr(pos+1);

        // 2.解析请求头
        left = right + 2;
        while (true)
        {
            right = buffer.find(SEP, left);
            if (left == right)
                break; // 3.找到空行结束
            if (right == string::npos)
            {
                return false;
            }
            int sp_pos = buffer.find(": ", left);
            string key = buffer.substr(left, sp_pos - left);
            string value = buffer.substr(sp_pos + 2, right - (sp_pos + 2));
            _header[key] = value;
            left = right + 2;
        }

        // 4.解析请求体
        left += 2;
        if (_header.count("Content-Length"))
        {
            
            int len = stoi(_header["Content-Length"]);
            _content = buffer.substr(left, len);
            if (_content.size() != len)
            {
                return false;
            }
            left+=len;
        }

        buffer.erase(0, left); // 将缓冲区中解析完成的数据去除
        return true;
    }

    int WriteFile()
    {
        ofstream ofs("./webroot/clientdata.html");
        if (!ofs.is_open())
            return -1;
        if(!_url_args.empty())
            ofs << "<p><h1>url_args: " << _url_args << "</h1></p>" << endl;
        if(!_content.empty())
            ofs << "<p><h1>content: " << _content << "</h1></p>" << endl;
        ofs.close();
        return _content.size();
    }

    void DebugPrint()
    {
        cout << "Request Line:" << endl;
        cout << "method: " << _method << endl;
        cout << "url: " << _url << endl;
        cout << "url_args: " << _url_args << endl;
        cout << "http_version: " << _http_version << endl;
        cout << endl;

        cout << "Header:" << endl;
        for (auto &[k, v] : _header)
        {
            cout << k << ": " << v << endl;
        }
        cout << endl;

        cout << "Body:" << endl;
        cout << _content << endl;
        cout << "-----------------------------------------------------------------------------" << endl;
    }
};

struct Response
{
    string _http_version;
    int _state_code;
    static unordered_map<int, string> _desc_map;
    static unordered_map<string, string> _content_types;
    unordered_map<string, string> _header;
    string _content;

    Response(const string &version)
        : _http_version(version)
    {
    }

    int ReadFile(const string &path)
    {
        ifstream ifs(path.c_str(), ifstream::binary);
        if (!ifs.is_open())
            return -1;
        ifs.seekg(0, ifs.end);
        int len = ifs.tellg();
        ifs.seekg(0, ifs.beg);
        _content.resize(len);
        ifs.read((char*)_content.c_str(), len);
        ifs.close();
        return len;
    }

    string Serialize()
    {
        stringstream ss;
        // 1.序列化响应行
        ss << _http_version << " " << to_string(_state_code) << " " << _desc_map[_state_code] << SEP;
        // 2.序列化响应头
        for (auto &[k, v] : _header)
        {
            ss << k << ": " << v << SEP;
        }
        // 3.空行
        ss << SEP;
        // 4.序列化响应体
        ss << _content;
        return ss.str();
    }
};

unordered_map<int, string> Response::_desc_map = {{200, "OK"}, {404, "Not Found"}, {302, "Found"}};
unordered_map<string, string> Response::_content_types = {{"html", "text/html"}, \
{"mp3", "audio/mp3"}, {"jpeg", "image/jpeg"}};
